﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
using MySQL.Db;

namespace Gollie
{
	public enum Role
	{
		SuperUser = 0,
		Administrator = 1,
		Sales = 2,
		Desk = 3,
		Customer = 4,
		Unknown = 99
	}

    public class UserInfo
    {
		public uint Id;
		public uint RoleId;
		public string Voorletters;
		public string Tussenvoegsel;
		public string Achternaam;
		public string Woonplaats;
		public string Email;
		public string Gebruikersnaam;
		public bool Geslacht;
		public DateTime Geboortedatum;
		public string Telefoon;
		public uint VendorId;
		public bool IsSecret = false;
		public DateTime PreviousLogin;
		public DateTime RegistratieDatum;
		internal bool IsAdmin = false;
		public string WebToken;
		public string Ip;
		public VendorInfo VendorInfo = null;

		private string bufferedQRCodePath = null;

		//admin
		internal UserInfo()
		{
			this.IsAdmin = true;
			this.Id = 0;
			this.RoleId = 0;
			this.Voorletters = "A";
			this.Achternaam = "Admin";
			this.Woonplaats = "H";
			this.Email = "administrator@gollie.nl";
			this.Gebruikersnaam = "Admin";
			this.Geslacht = true;
			this.Geboortedatum = new DateTime(1967, 9, 1);
			this.Telefoon = "0620231338";
			this.VendorId = 1;
			this.WebToken = "";
			this.VendorInfo = null;
		}

		internal UserInfo(ResultSet resultSet)
			: this(resultSet, 0)
		{ }

		internal UserInfo(ResultSet resultSet, int row)
		{
			uint io;

			this.Id = resultSet.GetUInt32(row, "id");
			this.Gebruikersnaam = resultSet.GetString(row, "username");

			io = resultSet.GetUInt32(row, "roleid");
			this.RoleId = (io == uint.MinValue ? 0 : io);

			this.Email = resultSet.GetString(row, "email");
			this.Voorletters = resultSet.GetString(row, "initials") ?? "";
			this.Tussenvoegsel = resultSet.GetString(row, "infix") ?? "";
			this.Achternaam = resultSet.GetString(row, "lastname") ?? "";
			this.Geslacht = resultSet.GetBool(row, "sex");
			this.Woonplaats = resultSet.GetString(row, "city") ?? "";
			this.Geboortedatum = resultSet.GetDateTime(row, "birthdate");
			this.Telefoon = resultSet.GetString(row, "mobile") ?? "";

			io = resultSet.GetUInt32(row, "vendorid");
			this.VendorId = (io == uint.MinValue ? 0 : io);

			this.RegistratieDatum = resultSet.GetDateTime(row, "registrationdate");
			this.PreviousLogin = resultSet.GetDateTime(row, "lastlogindate");

			if (this.VendorId != 1)
				this.VendorInfo = VendorInfo.GetVendorInfo(this.VendorId);

			this.WebToken = resultSet.GetString(row, "webtoken");

			this.Ip = ObjectFormatter.CurrentIp;
		}

		internal UserInfo(string voorLetters, string tussenvoegsel, string achternaam, bool geslacht, string email)
		{
			this.Voorletters = voorLetters;
			this.Tussenvoegsel = tussenvoegsel;
			this.Achternaam = achternaam;
			this.Geslacht = geslacht;
			this.Email = email;

			this.Ip = ObjectFormatter.CurrentIp;
		}

		internal static UserInfo GetUserInfo(int userId)
		{
			return GetUserInfo(userId, true);
		}

		internal static UserInfo GetUserInfo(int userId, bool hasToBeActivated)
		{
			return Database.Queries.GetUser(userId, hasToBeActivated);
		}

		internal static UserInfo GetUserInfo(string userName)
		{
			return GetUserInfo(userName, true);
		}

		internal static UserInfo GetUserInfo(string userName, bool hasToBeActivated)
		{
			return Database.Queries.GetUser(userName, hasToBeActivated);
		}

		internal string Bedrijfsnaam
		{
			get
			{
				return (this.VendorInfo == null ? "" : this.VendorInfo.BedrijfsNaam);
			}
		}

		internal string MailAanhef
		{
			get
			{
				StringBuilder str = new StringBuilder("Geachte ", 256);

				str.Append(this.Geslacht ? "heer " : "mevrouw ");
				str.Append(this.FullName);
				str.Append(",");
				str.Append("<br><br>");

				return str.ToString();
			}
		}

		internal string FullName
		{
			get
			{
				return GetFullName(this.Voorletters, this.Tussenvoegsel, this.Achternaam);
			}
		}

		internal static string GetFullName(string initials, string infix, string lastName)
		{
			if (string.IsNullOrEmpty(lastName) || string.IsNullOrEmpty(initials))
				return null;

			StringBuilder str = new StringBuilder(initials);

			if (initials.EndsWith(".") == false)
				str.Append('.');

			str.Append(" ");
			if (string.IsNullOrEmpty(infix) == false)
			{
				str.Append(infix);
				str.Append(" ");
			}
			str.Append(lastName);

			return str.ToString();
		}

		internal string QRCodeNumber
		{
			get
			{
				if (this.Role != Gollie.Role.Customer)
					return null; 
				
				return this.Id.ToString("0000000000");
			}
		}

		internal string QRCodeFile
		{
			get
			{
				if (this.Role != Gollie.Role.Customer)
					return null; 

				return "Gollie_" + this.QRCodeNumber + ".png";
			}
		}

		internal string QRCodePath
		{
			get
			{
				if (this.Role !=  Gollie.Role.Customer)
					return null;

				if (this.bufferedQRCodePath == null)
					this.bufferedQRCodePath = System.IO.Path.Combine(ConfigAppSettings.GetValue("QRCodeFolder"), this.QRCodeFile);

				return this.bufferedQRCodePath;
			}
		}

		internal Role Role
		{
			get
			{
				Role role = Gollie.Role.Unknown;

				switch (this.RoleId)
				{
					case 0: role = Gollie.Role.SuperUser; break;
					case 1: role = Gollie.Role.Administrator; break;
					case 2: role = Gollie.Role.Sales; break;
					case 3: role = Gollie.Role.Desk; break;
					case 4: role = Gollie.Role.Customer; break;
				}

				return role;
			}
		}

		internal static void ValidateUserName(string arg)
		{
			if (arg.Length < 6 || arg.Length > 16)
				throw new ArgumentException("Gebruikersnaam is minimaal zes en maximaal 16 posities lang");

			if (arg.StartsWith("("))
				throw new ArgumentException("Gebruikersnaam mag niet met een ( beginnen");
		}

		internal static void ValidateWW(string arg) { ValidateWW(arg, false); }
		internal static void ValidateWW(string arg, bool allowEmpty)
		{
			if (allowEmpty && string.IsNullOrEmpty(arg))
				return;

			if (arg.Length < 6)
				throw new ArgumentException("Wachtwoord is minimaal zes posities lang");
		}

		internal static void ValidateEmail(string arg)
		{
			if (Gollie.Mail.EMail.IsEmailAddressValid(arg) == false)
				throw new ArgumentException("Ongeldig e-mail adres");
		}

		internal static string ValidateTelePhone(string arg, bool mobileOnly)
		{
			string regex = mobileOnly ? "^(00316|\\+316|06)[- ]?\\d{8}$" : "^(0031|\\+31|0)\\d{9}$";
			if (System.Text.RegularExpressions.Regex.IsMatch(arg, regex))
				arg = "+31" + arg.Substring(arg.Length - 9);
			else
				throw new ArgumentException("Ongeldig telefoonnummer");

			return arg;
		}

		internal static void ValidatePin(string arg) { ValidatePin(arg, false); }
		internal static void ValidatePin(string arg, bool allowEmpty)
		{
			if (allowEmpty && string.IsNullOrEmpty(arg))
				return;

			if (System.Text.RegularExpressions.Regex.IsMatch(arg, "^\\d{4}$") == false)
				throw new ArgumentException("Pincode dient uit 4 cijfers te bestaan");
		}

		internal static DateTime ValidateBirthdate(string arg)
		{
			DateTime bdate;
			if (DateTime.TryParse(arg, out bdate) == false)
				throw new ArgumentException("Geboortedatum is niet correct (dd-mm-jjjj)");

			if (Calculator.Age(bdate) < 18) //the 'minus 1' is correct !!
				throw new ArgumentException("U dient ten minste 18 jaar te zijn");

			return bdate;
		}

		internal static string ValidateInitials(string arg)
		{
			if (string.IsNullOrEmpty(arg))
				throw new ArgumentException("Voorletters niet ingevuld");

			string initials = arg.ToUpper();
			StringBuilder str = new StringBuilder();
			foreach (char c in initials.Where(x => char.IsLetter(x)))
			{
				str.Append(c); str.Append('.');
			}

			if (str.Length > 16)
				throw new ArgumentException("Voorletters is maximaal 16 posities lang");

			return str.ToString();
		}
    }
}